package org.dync.giftlibrary.widget;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.StackLayout;
import ohos.agp.components.Text;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.global.resource.Resource;
import ohos.global.resource.ResourceManager;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.Size;
import org.dync.giftlibrary.ResourceTable;
import org.dync.giftlibrary.util.GiftAnimationUtil;
import org.dync.giftlibrary.util.HeLog;
import org.dync.giftlibrary.util.glide.GlideCircleTransform;
import org.dync.giftlibrary.util.glide.GlideLoader;

import java.io.IOException;

/**
 * Created by KathLine on 2017/1/8.
 */
public class GiftFrameLayout extends StackLayout {
    private static final String TAG = "GiftFrameLayout";
    private LayoutScatter mInflater;
    private Context mContext;
    private mEventHandler mHandler = new mEventHandler(EventRunner.getMainEventRunner());//连击handler
    private EventHandler comboHandler = new EventHandler(EventRunner.getMainEventRunner());//检查连击handler
    private Runnable runnable;

    private class mEventHandler extends EventHandler {
        private mEventHandler(EventRunner runner) {
            super(runner);
        }

        // 重写实现processEvent方法
        @Override
        public void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (event == null) {
                return;
            }
            int eventId = event.eventId;
            switch (eventId) {
                case RESTART_GIFT_ANIMATION_CODE:
                    if (mJumpCombo > 0) {
                        mCombo += mJumpCombo;
                    } else {
                        ++mCombo;
                    }
                    anim_num.setText("x " + (mCombo));
                    comboAnimation(false);
                    removeDismissGiftCallback();
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 实时监测礼物数量
     */
    private static final int RESTART_GIFT_ANIMATION_CODE = 1002;
    /**
     * 礼物展示时间
     */
    public static final int GIFT_DISMISS_TIME = 3000;
    private static final int INTERVAL = 299;
    /**
     * 当前动画runnable
     */
    private Runnable mCurrentAnimRunnable;

    DependentLayout anim_rl;
    Image anim_gift, anim_light, anim_header;
    Text anim_nickname, anim_sign;
    StrokeTextView anim_num;

    private GiftModel mGift;
    /**
     * item 显示位置
     */
    private int mIndex = 1;
    /**
     * 礼物连击数
     */
    private int mGiftCount;
    /**
     * 当前播放连击数
     */
    private int mCombo = 0;
    /**
     * 跳到指定连击数，例如：从1直接显示3，这里的值就是2
     */
    private int mJumpCombo = 0;
    /**
     * 礼物动画正在显示，在这期间可触发连击效果
     */
    private boolean isShowing = false;
    /**
     * 礼物动画结束
     */
    private boolean isEnd = true;
    /**
     * 自定义动画的接口
     */
    private ICustormAnim anim;
    /**
     * 是否开启礼物动画隐藏模式（如果两个礼物动画同时显示，并且第一个优先结束，第二个礼物的位置会移动到第一个位置上去）
     */
    private boolean isHideMode = false;

    private LeftGiftAnimationStatusListener mGiftAnimationListener;
    private Component rootView;

    public GiftFrameLayout(Context context) {
        this(context, null);
    }

    public GiftFrameLayout(Context context, AttrSet attrSet) {
        super(context, attrSet);
        mInflater = LayoutScatter.getInstance(context);
        mContext = context;
        initView();

    }

    private void initView() {
        rootView = mInflater.parse(ResourceTable.Layout_item_gift, null, false);
        anim_rl = (DependentLayout) rootView.findComponentById(ResourceTable.Id_infoRl);
        anim_gift = (Image) rootView.findComponentById(ResourceTable.Id_giftIv);
        anim_light = (Image) rootView.findComponentById(ResourceTable.Id_light);
        anim_num = (StrokeTextView) rootView.findComponentById(ResourceTable.Id_animation_num);
        anim_header = (Image) rootView.findComponentById(ResourceTable.Id_headIv);
        anim_nickname = (Text) rootView.findComponentById(ResourceTable.Id_nickNameTv);
        anim_sign = (Text) rootView.findComponentById(ResourceTable.Id_infoTv);
        this.addComponent(rootView);
    }

    public Image getAnimGift() {
        return anim_gift;
    }

    public void firstHideLayout() {
        AnimatorProperty animator = new AnimatorProperty();
        animator.alphaFrom(1.0f);
        animator.alpha(0f);
        animator.setTarget(GiftFrameLayout.this);
        animator.setDelay(0);
        animator.setDuration(0);
        animator.start();
    }

    public void setHideMode(boolean isHideMode) {
        this.isHideMode = isHideMode;
    }

    public void hideView() {
        anim_gift.setVisibility(INVISIBLE);
        anim_light.setVisibility(INVISIBLE);
        anim_num.setVisibility(INVISIBLE);
    }

    public void setGiftViewEndVisibility(boolean hasGift) {

        if (isHideMode && hasGift) {
            GiftFrameLayout.this.setVisibility(Component.HIDE);
        } else {
            GiftFrameLayout.this.setVisibility(Component.INVISIBLE);
        }
    }

    public boolean setGift(GiftModel gift) {
        if (gift == null) {
            return false;
        }
        mGift = gift;

        if (mGift.isCurrentStart()) {
            mGiftCount = gift.getGiftCount() + mGift.getHitCombo();
        } else {
            mGiftCount = gift.getGiftCount();
        }
        mJumpCombo = mGift.getJumpCombo();

        if (gift.getSendUserName() != null && gift.getSendUserName().length() > 0) {
            anim_nickname.setText(gift.getSendUserName());
        }
        if (gift.getGiftId() != null && gift.getGiftId().length() > 0) {
            anim_sign.setText(gift.getGiftName());
        }
        return true;
    }

    public GiftModel getGift() {
        return mGift;
    }

    /**
     * 显示完连击数与动画时,关闭此Item Layout,并通知外部隐藏自身(供内部调用)
     */
    private void dismissGiftLayout() {
        removeDismissGiftCallback();
        if (mGiftAnimationListener != null) {
            mGiftAnimationListener.dismiss(this);
        }
    }

    private void removeDismissGiftCallback() {
        comboHandler.removeAllEvent();
        if (mCurrentAnimRunnable != null) {
            mHandler.removeTask(mCurrentAnimRunnable);
            mCurrentAnimRunnable = null;
        }
    }

    private class GiftNumAnimaRunnable implements Runnable {
        @Override
        public void run() {
            dismissGiftLayout();
        }
    }

    /**
     * 设置item显示位置
     *
     * @param mIndex
     */
    public void setIndex(int mIndex) {
        this.mIndex = mIndex;
    }

    /**
     * 获取ite显示位置
     *
     * @return int
     */
    public int getIndex() {
        HeLog.d(TAG, "index : " + mIndex);
        return mIndex;
    }

    public interface LeftGiftAnimationStatusListener {
        void dismiss(GiftFrameLayout giftFrameLayout);
    }

    public void setGiftAnimationListener(LeftGiftAnimationStatusListener giftAnimationListener) {
        this.mGiftAnimationListener = giftAnimationListener;
    }

    public boolean isShowing() {
        return isShowing;
    }

    public void setCurrentShowStatus(boolean status) {
        mCombo = 0;
        isShowing = status;
    }

    public boolean isEnd() {
        return isEnd;
    }

    public void CurrentEndStatus(boolean isEnd) {
        this.isEnd = isEnd;
    }

    /**
     * 获取当前显示礼物发送人id
     *
     * @return String
     */
    public String getCurrentSendUserId() {
        if (mGift != null) {
            return mGift.getSendUserId();
        }
        return null;
    }

    /**
     * 获取当前显示礼物id
     *
     * @return String
     */
    public String getCurrentGiftId() {
        if (mGift != null) {
            return mGift.getGiftId();
        }
        return null;
    }

    /**
     * 增加礼物数量,用于连击效果
     *
     * @param count
     */
    public synchronized void setGiftCount(int count) {
        HeLog.d(TAG, "setGiftCount: " + count);
        mGiftCount += count;
        mGift.setGiftCount(mGiftCount);
    }



    public synchronized void setSendGiftTime(long sendGiftTime) {
        mGift.setSendGiftTime(sendGiftTime);
    }



    public boolean isCurrentStart() {
        return mGift.isCurrentStart();
    }

    public void setCurrentStart(boolean currentStart) {
        mGift.setCurrentStart(currentStart);
    }

    public int getCombo() {
        return mCombo;
    }

    public int getJumpCombo() {
        return mJumpCombo;
    }

    /**
     * <pre>
     * 这里不能GIFT_DISMISS_TIME % INVISIBLE == 0,
     * 因为余数为0的话，说明在这个时刻即执行了移除动画{@link #endAnmation(ICustormAnim)},也执行了检查监听连击动作。
     * 这导致就会出现在礼物动画消失的一瞬间，点击连击会出现如下日志出现的情况（已经触发连击了，但是礼物的动画已经结束了）：
     * 02-18 20:45:57.900 9060-9060/org.dync.livegiftlayout D/GiftControl: addGiftQueue---集合个数：0,礼物：p/000.png
     * 02-18 20:45:57.900 9060-9060/org.dync.livegiftlayout D/GiftControl: showGift: begin->集合个数：1
     * 02-18 20:45:57.900 9060-9060/org.dync.livegiftlayout I/GiftControl: getGift---集合个数：0,送出礼物---p/000.png,礼物数X1
     * 02-18 20:45:57.910 9060-9060/org.dync.livegiftlayout D/GiftControl: showGift: end->集合个数：0
     * 02-18 20:46:01.910 9060-9060/org.dync.livegiftlayout I/GiftControl: addGiftQueue: ========mFirstItemGift连击========礼物：p/000.png,连击X1
     * 02-18 20:46:01.970 9060-9060/org.dync.livegiftlayout D/GiftControl: reStartAnimation: 动画结束
     * 02-18 20:46:02.490 9060-9060/org.dync.livegiftlayout I/GiftControl: 礼物动画dismiss: index = 0
     *
     * </pre>
     */
    private void checkGiftCountSubscribe() {
        runnable = new Runnable() {
            @Override
            public void run() {
                if (mGiftCount > mCombo) {
                    mHandler.sendEvent(RESTART_GIFT_ANIMATION_CODE);
                }
                comboHandler.postTask(runnable, INTERVAL);
            }
        };
        comboHandler.postTask(runnable, INTERVAL);
    }

    public void clearHandler() {
        if (mHandler != null) {
            mHandler.removeAllEvent();
            mHandler = null;//这里要置位null，否则当前页面销毁时，正在执行的礼物动画会造成内存泄漏
        }

        mGiftAnimationListener = null;

        if (comboHandler != null) {
            comboHandler.removeAllEvent();
            comboHandler = null;//这里要置位null，否则当前页面销毁时，正在执行的礼物动画会造成内存泄漏
        }
        resetGift();
    }

    public void resetGift() {
        runnable = null;
        mCurrentAnimRunnable = null;
        mGift = null;
        mIndex = -1;
        mGiftCount = 0;
        mCombo = 0;
        mJumpCombo = 0;
        isShowing = false;
        isEnd = true;
        isHideMode = false;
    }

    /**
     * 动画开始时回调，使用方法借鉴{@link #startAnimation}
     */
    public void initLayoutState() {
        this.setVisibility(Component.VISIBLE);
        isShowing = true;
        isEnd = false;
        Glide.with(mContext).load(ResourceTable.Media_head).apply(new RequestOptions().circleCrop()).into(anim_header);

        if (mGift.isCurrentStart()) {
            mCombo = mGift.getHitCombo();
        }
        anim_num.setVisibility(INVISIBLE);
        anim_num.setText("x " + mCombo);

        if (!mGift.getGiftPic().equals("")) {
            GlideLoader.init()
                    .load(mGift.getGiftPic())
                    .applyDefault()
                    .bitmapTransform(new GlideCircleTransform())
                    .into(anim_gift);
        } else {
            try {
                ResourceManager manager = getResourceManager();
                Resource resource1 = manager.getRawFileEntry(mGift.getGiftId()).openRawFile();
                ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
                ImageSource imageSource = ImageSource.create(resource1, sourceOptions);
                ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
                decodingOptions.desiredSize = new Size(120, 120);
                PixelMap pixelMap = imageSource.createPixelmap(decodingOptions);
                anim_gift.setPixelMap(pixelMap);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 连击结束时回调
     */
    public void comboEndAnim() {
        if (mHandler != null) {
            if (mGiftCount > mCombo) {//连击
                mHandler.sendEvent(RESTART_GIFT_ANIMATION_CODE);
            } else {
                mCurrentAnimRunnable = new GiftNumAnimaRunnable();
                mHandler.postTask(mCurrentAnimRunnable, GIFT_DISMISS_TIME);
                checkGiftCountSubscribe();
            }
        }
    }

    public Animator startAnimation(ICustormAnim anim) {
        this.anim = anim;
        if (anim == null) {
            hideView();
            //布局飞入
            AnimatorProperty flyFromLtoR = GiftAnimationUtil.createFlyFromLtoR(anim_rl, -getWidth(), 0, 400, null);
            flyFromLtoR.setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {
                    initLayoutState();
                }

                @Override
                public void onStop(Animator animator) {
                }

                @Override
                public void onCancel(Animator animator) {
                }

                @Override
                public void onEnd(Animator animator) {
                }

                @Override
                public void onPause(Animator animator) {
                }

                @Override
                public void onResume(Animator animator) {
                }
            });

            //礼物飞入
            AnimatorProperty flyFromLtoR2 = GiftAnimationUtil.createFlyFromLtoR(anim_gift, -getWidth(), 0, 400, null);
            flyFromLtoR2.setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {
                    anim_gift.setVisibility(Component.VISIBLE);
                }

                @Override
                public void onStop(Animator animator) {

                }

                @Override
                public void onCancel(Animator animator) {

                }

                @Override
                public void onEnd(Animator animator) {
                    comboAnimation(true);
                }

                @Override
                public void onPause(Animator animator) {

                }

                @Override
                public void onResume(Animator animator) {

                }
            });
            AnimatorGroup animatorSet = GiftAnimationUtil.startAnimation(flyFromLtoR, flyFromLtoR2);

            return animatorSet;
        } else {
            return anim.startAnim(this, rootView);
        }
    }

    public void comboAnimation(boolean isFirst) {
        if (anim == null) {
            if (isFirst) {
                GiftAnimationUtil.startAnimationDrawable(anim_light);
                anim_num.setVisibility(Component.VISIBLE);
                anim_num.setText("x " + mCombo);
                comboEndAnim();
            } else {
                //数量增加
                AnimatorValue scaleGiftNum = GiftAnimationUtil.scaleGiftNum(anim_num);
                scaleGiftNum.setStateChangedListener(new Animator.StateChangedListener() {
                    @Override
                    public void onStart(Animator animator) {

                    }

                    @Override
                    public void onStop(Animator animator) {

                    }

                    @Override
                    public void onCancel(Animator animator) {

                    }

                    @Override
                    public void onEnd(Animator animator) {
                        comboEndAnim();
                    }

                    @Override
                    public void onPause(Animator animator) {

                    }

                    @Override
                    public void onResume(Animator animator) {

                    }
                });
                scaleGiftNum.start();
            }
        } else {
            anim.comboAnim(this, rootView, isFirst);
        }
    }

    public Animator endAnmation(ICustormAnim anim) {
        if (anim == null) {
            //向上渐变消失
            AnimatorProperty fadeAnimator = GiftAnimationUtil.createFadeAnimator(rootView, 0, -100, 500, 0);
            fadeAnimator.setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {

                }

                @Override
                public void onStop(Animator animator) {

                }

                @Override
                public void onCancel(Animator animator) {

                }

                @Override
                public void onEnd(Animator animator) {
                    anim_num.setVisibility(Component.INVISIBLE);
                }

                @Override
                public void onPause(Animator animator) {

                }

                @Override
                public void onResume(Animator animator) {

                }
            });
            // 复原
            AnimatorProperty fadeAnimator2 = GiftAnimationUtil.createFadeAnimator(rootView, 100, 0, 0, 0);

            AnimatorGroup animatorSet = GiftAnimationUtil.startAnimation(fadeAnimator, fadeAnimator2);
            return animatorSet;
        } else {
            return anim.endAnim(this, rootView);
        }
    }
}
